﻿using System;
using System.Threading;

namespace Dimebrain.TweetSharp.Core.Tasks
{
    /// <summary>
    /// Class representing a recurring task
    /// </summary>
    public class TimedTask : IDisposable
    {
        private readonly Timer _timer;
        private readonly TimeSpan _interval;
        private readonly TimeSpan _due;
        private readonly int _iterations;

        /// <summary>
        /// Gets or sets the action to perform periodically.
        /// </summary>
        /// <value>The action.</value>
        public Action Action { get; private set; }
        
        /// <summary>
        /// The last exception that occurred during a timed action.
        /// </summary>
        public Exception Exception { get; private set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="TimedTask"/> class.
        /// </summary>
        /// <param name="due">The next time to perform the task.</param>
        /// <param name="interval">The recurrance interval for the task.</param>
        /// <param name="continueOnError">if set to <c>true</c> [continue on error].</param>
        /// <param name="iterations">The number of times to perform the task. If zero, performs the task continuously.</param>
        /// <param name="action">The action to perform.</param>
        public TimedTask(TimeSpan due, TimeSpan interval, bool continueOnError, int iterations, Action action)
        {
            Action = action;

            _due = due;
            _interval = interval;
            _iterations = iterations;
            var count = 0;

            _timer = new Timer(state =>
                               {
                                   try
                                   {
                                       Action();
                                       count++;

                                       if (_iterations > 0 && _iterations >= count)
                                       {
                                           Stop();
                                       }
                                   }
                                   catch (Exception ex)
                                   {
                                       Exception = ex;
                                       if (!continueOnError)
                                       {
                                           Stop();
                                       }
                                   }
                               }, null, _due, _interval);
        }

        /// <summary>
        /// Stops this task instance.
        /// </summary>
        public void Stop()
        {
            _timer.Change(-1, -1);
        }

        /// <summary>
        /// Starts this task instance.
        /// </summary>
        public void Start()
        {
            _timer.Change(_due, _interval);
        }

        public void Dispose()
        {
            _timer.Dispose();
        }
    }
}